home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / ed3_1_1 / part03 / freq.c < prev   
C/C++ Source or Header  |  1991-11-07  |  20KB  |  677 lines

  1. /*
  2.     This module of of ed3 devoted to raising polyhedra to
  3.     higher frequencies.
  4.  
  5. 10-13-91 frequency() now checks to see if there is room in the undo buf
  6. 09-19-91 found tiny bug (missing a -1) on line 385.  It caused glitches.
  7. 08-26-91 fixed small (final?) bug in freq algo
  8. 08-24-91 attempt to extend algorithm to quadrilaterals.
  9.         We could try to do this by doubling the complexity of the
  10.         current code (same size, double complex) or by doubling
  11.         the size.  Having a second type of shape (quads) could mean
  12.         4 times the complexity (n^2 effect!).
  13. */
  14.  
  15. #include "sysnogr.h"
  16.  
  17.  
  18. /*   freq = 1       freq = 2       freq = 3   etc.
  19.         A              A              A
  20.        / \            / \            / \
  21.       /   \          /   \          0---1
  22.      /     \ ->     0-----1  ->    / \ / \   ->
  23.     /       \      / \   / \      2---3---4
  24.    /         \    /   \ /   \    / \ / \ / \
  25.   B-----------C  B-----2-----C  B---5---6---C
  26.  
  27.     This algorithm is careful not to duplicate the (already existing)
  28.     vertices of the current triangles.  It should also not duplicate the
  29.     frequency edge vertices of adjacent faces.  Note that this algorithm
  30.     will work for ANY frequency, however frequencies beyond 5 would
  31.     require recompiling with a larger second dimension to the edge_point
  32.     array in FaceInfo, to hold more edge points.  Rotation sense of the
  33.     triangle's points is maintained (same as the original triangle).
  34.  
  35. Added on 8-24-91: Quadrilateral support!
  36.  
  37.          freq = 1           freq = 2             freq = 3
  38.  
  39.             A                    A                    A
  40.            / \                  / \                  / \
  41.           /   \                /   \                /   0
  42.          /     \              /     0              /     \
  43.         /       \            /     / \            2       1
  44.        /         \          /     /   \          /   3     \
  45.       /           D        1-    |     D        /           D
  46.      /            |       /  \-  /     |       /         4  |
  47.     /             |      /     \2---   |      6    7        5
  48.    /              |     /       |   \--3     /          8   |
  49.   /               |    /       /       |    /               9
  50.  /                |   /       |        |   /                |
  51. B-----------------C  B--------4--------C  B---10---11---12--C
  52.  
  53.  
  54.     Quadrilaterals divide into the same number of sections as triangles, but
  55. require more points to do so.  Quad support was added so that you can do
  56. frequency operations on cuboctahedrons, cubes, rhombic dodecahedrons, etc.
  57.  
  58. */
  59.  
  60.  
  61. struct FaceInfo {            /* info that each face needs to know */
  62.     uindex index[3];        /* concerning what faces are adjacent */
  63.     short kind[3];            /* which kind of shape is adjacent */
  64.     unsigned present : 3,    /* IF there is one */
  65.              direction : 3,    /* HOW: 0 is normal, 1 is reverse */
  66.              edge : 6;        /* WHICH edge of the adjacent face */
  67.     uindex edge_point[3][4];/* allows up to freq. 5: [3][f-1] */
  68. };
  69.  
  70. struct QuadInfo {            /* info that each 4-sided poly needs to know */
  71.     uindex poly;            /* the index of the corresponding polygon */
  72.     uindex index[4];        /* concerning what faces are adjacent */
  73.     short kind[4];            /* which kind of shape is adjacent */
  74.     unsigned present : 4,    /* IF there is one */
  75.              direction : 4,    /* HOW: 0 is normal, 1 is reverse */
  76.              edge : 8;        /* WHICH edge of the adjacent face */
  77.     uindex edge_point[4][4];/* allows up to freq. 5: [4][f-1] */
  78. };
  79.  
  80. /* values for the "kind" field in the above structures */
  81. #define K_FACE    1
  82. #define K_QUAD    2
  83.  
  84.  
  85. void frequency()
  86. {
  87.     int id, freq, err, event;
  88.     int go = 1;
  89.     int quads, add_p, add_f, del_f, add_q, del_q;
  90.     index po0;
  91.  
  92.     freq = 3;
  93.     sys_window(34, 2, "Tesselate Polyhedron");
  94.     sys_movecur(1,0);
  95.     sys_say_text("to Frequency (2..7):");
  96.     sys_get_long(freq, 1);
  97.     sys_activate(1);
  98.  
  99.     while (go)
  100.     {
  101.         event = sys_read_event(&id, &freq);
  102.         switch (event)
  103.         {
  104.             case EV_CANCEL:
  105.                 sys_close_window();
  106.                 return;
  107.                 break;
  108.             case EV_CHECKINT:
  109.             case EV_HITRETURN:
  110.                 if (freq > 7) freq = 7;
  111.                 if (freq < 2) freq = 2;
  112.                 if (event == EV_HITRETURN) go = 0;
  113.                 break;
  114.         }
  115.     }
  116.     sys_close_window();
  117.  
  118.     /* Estimate how many actions the tesselation will require. */
  119.     /* Assume the worst case of all facets non-adjacent */
  120.     /* count how many quads we've got */
  121.     quads = 0;
  122.     for (po0 = 0; po0 < polys; po0++)
  123.         if (poly[po0].verts == 4) quads++;
  124.     add_p = faces * (fibo(freq + 1) - 3);    /* for the faces */
  125.     add_p += quads * ((freq * freq) - 4);    /* for the quads */
  126.     add_f = faces * freq * freq;
  127.     del_f = faces;
  128.     add_q = quads * freq * freq;
  129.     del_q = quads;
  130.  
  131.     /* Make sure that this event won't overflow the undo buffer */
  132.     if (!enough_room(add_p, add_f, add_q, 0, del_f, del_q, 0, 4))
  133.     {
  134.         /* this operation will overflow the undo buffer! */
  135.         if (!tell_user_overflow()) return;
  136.     }
  137.  
  138.     begin_operation();
  139.     err = bucky_frequency(freq);
  140.     end_operation();
  141. }
  142.  
  143.  
  144. bucky_frequency(freq)
  145. short freq;
  146. {
  147.     index f, f2;        /* each face, signed for backwards loop */
  148.     index q, q2;        /* each quad, signed for backwards loop */
  149.     index fpoint[21];    /* allows frequencies of up to 5: (f+1)(f+2)/2 */
  150.     index fpoints;        /* temporary indices for current face triangle */
  151.     index qpoint[42];    /* allows frequencies of up to 5: (f+1)(f+2) */
  152.     index qpoints;        /* temporary indices for current quad */
  153.     index prev;            /* index of point at start of last row */
  154.     index row, i;        /* loops */
  155.     uindex p0, p1, p2, p3;
  156.     uindex e, e2;        /* edges */
  157.     Point3D vec[3],        /* 2 or 3 edge vectors, face or quad */
  158.            start,        /* coordinates of the start of each row */
  159.            end;            /* (for quads) coords of the end of each row */
  160.     uindex old_faces = faces;
  161.     uindex old_polys = polys;
  162.     struct FaceInfo *finfo = 0L, fcurrent;
  163.     struct QuadInfo *qinfo = 0L, qcurrent;
  164.     uindex adj_face, adj_quad, adj_edge, pos;
  165.     char add_the_point, flag;
  166.     index po0, po1;            /* polygon counter */
  167.     index quads;
  168.  
  169.     /* count how many quads we've got */
  170.     quads = 0;
  171.     for (po0 = 0; po0 < polys; po0++)
  172.         if (poly[po0].verts == 4) quads++;
  173.  
  174.     if (!faces && !quads) return OKAY;    /* must have SOMETHING to operate on */
  175.  
  176.     if (freq < 2 || freq > 20) return OKAY;
  177.  
  178.     /* we need to allocate memory, since the number of faces is variable */
  179.     if (faces)
  180.     {
  181.         if (flags.debug)
  182.             printf("allocating %d bytes for faces\n", faces*sizeof(struct FaceInfo));
  183.         finfo = (struct FaceInfo *)sys_alloc(faces*sizeof(struct FaceInfo));
  184.         if (!finfo)
  185.         {
  186.             screen_say("Not enough memory for that frequency");
  187.             return ERR_NOMEM;
  188.         }
  189.     }
  190.     if (quads)
  191.     {
  192.         if (flags.debug)
  193.             printf("allocating %d bytes for quads\n", quads*sizeof(struct QuadInfo));
  194.         qinfo = (struct QuadInfo *)sys_alloc(quads*sizeof(struct QuadInfo));
  195.         if (!qinfo)
  196.         {
  197.             screen_say("Not enough memory for that frequency");
  198.             return ERR_NOMEM;
  199.         }
  200.     }
  201.  
  202.     /* we need to link our QuadInfo structures with real polygons */
  203.     quads = 0;
  204.     for (po0 = 0; po0 < polys; po0++)
  205.         if (poly[po0].verts == 4)
  206.             qinfo[quads++].poly = po0;
  207.  
  208.     if (flags.debug) printf("frequency %d\n", freq);
  209.  
  210. /*  Before triangulating, we scan all the faces and quads and assign each edge
  211.     a "master" face/quad that "owns" that edge.  Later, only this face/quad
  212.     will add vertice points along this edge.  The last face/quad will always
  213.     add    all it's edges.
  214. */
  215.  
  216.     for (f = 0; f < faces; f++)
  217.     {
  218.          finfo[f].present = 0;    /* by default, DO add the edge. */
  219.          finfo[f].direction = 0;
  220.          finfo[f].edge = 0;
  221.  
  222. /**** Compare faces against faces */
  223.  
  224.         for (f2 = f+1; f2 < faces; f2++)
  225.         {
  226.             for (e = 0; e < 3; e++)
  227.             {
  228.                 p0 = face[f].p[e];
  229.                 p1 = face[f].p[(e+1)%3];
  230.  
  231.                 for (e2 = 0; e2 < 3; e2++)
  232.                 {
  233.                     /* There are two ways that one edge can match another:
  234.                         the point numbers can be identical or inverted.
  235.                         Edge i has indices i, (i+1)%3 for i = 0,1,2.
  236.                     */
  237.                     p2 = face[f2].p[e2];
  238.                     p3 = face[f2].p[(e2+1)%3];
  239.                     flag = 0;
  240.                     if (p0 == p2 && p1 == p3)
  241.                     {
  242.                         flag = 1;
  243.                     }
  244.                     else if (p0 == p3 && p1 == p2)
  245.                     {
  246.                         finfo[f].direction |= 1<<e;
  247.                         flag = 1;
  248.                     }
  249.                     if (flag)
  250.                     {
  251.                         finfo[f].present |= 1<<e;
  252.                         finfo[f].kind[e] = K_FACE;
  253.                         finfo[f].index[e] = f2;
  254.                         finfo[f].edge |= (e2 << (e << 1));
  255.                         break;
  256.                     }    
  257.                 }
  258.             }
  259.         }
  260.  
  261. /**** Compare faces against quads */
  262.  
  263.         for (q2 = 0; q2 < quads; q2++)
  264.         {
  265.             po1 = qinfo[q2].poly;
  266.             for (e = 0; e < 3; e++)
  267.             {
  268.                 p0 = face[f].p[e];
  269.                 p1 = face[f].p[(e+1)%3];
  270.  
  271.                 for (e2 = 0; e2 < 4; e2++)
  272.                 {
  273.                     p2 = poly[po1].p[e2];
  274.                     p3 = poly[po1].p[(e2+1)%4];
  275.                     flag = 0;
  276.                     if (p0 == p2 && p1 == p3)
  277.                     {
  278.                         flag = 1;
  279.                     }
  280.                     else if (p0 == p3 && p1 == p2)
  281.                     {
  282.                         finfo[f].direction |= 1<<e;
  283.                         flag = 1;
  284.                     }
  285.                     if (flag)
  286.                     {    
  287.                         finfo[f].present |= 1<<e;
  288.                         finfo[f].kind[e] = K_QUAD;
  289.                         finfo[f].index[e] = q2;
  290.                         finfo[f].edge |= (e2 << (e << 1));
  291.                         break;
  292.                     }
  293.                 }
  294.             }
  295.         }
  296.     }
  297.  
  298. /**** Compare quads against quads */
  299.  
  300.     for (q = 0; q < quads-1; q++)
  301.     {
  302.         qinfo[q].present = 0;    /* by default, DO add the edge. */
  303.         qinfo[q].direction = 0;
  304.         qinfo[q].edge = 0;
  305.         po0 = qinfo[q].poly;
  306.  
  307.         for (q2 = q+1; q2 < quads; q2++)
  308.         {
  309.             po1 = qinfo[q2].poly;
  310.             for (e = 0; e < 4; e++)
  311.             {
  312.                 p0 = poly[po0].p[e];
  313.                 p1 = poly[po0].p[(e+1)%4];
  314.  
  315.                 for (e2 = 0; e2 < 4; e2++)
  316.                 {
  317.                     p2 = poly[po1].p[e2];
  318.                     p3 = poly[po1].p[(e2+1)%4];
  319.                     flag = 0;
  320.                     if (p0 == p2 && p1 == p3)
  321.                     {
  322.                         flag = 1;
  323.                     }
  324.                     else if (p0 == p3 && p1 == p2)
  325.                     {
  326.                         qinfo[q].direction |= 1<<e;
  327.                         flag = 1;
  328.                     }
  329.                     if (flag)
  330.                     {    
  331.                         qinfo[q].present |= 1<<e;
  332.                         qinfo[q].kind[e] = K_QUAD;
  333.                         qinfo[q].index[e] = q2;
  334.                         qinfo[q].edge |= (e2 << (e << 1));
  335.                         break;
  336.                     }    
  337.                 }
  338.             }
  339.         }
  340.     }
  341.     /* the last quad is always MASTER! AH ha ha! */
  342.      if (quads) qinfo[quads-1].present = 0;
  343.  
  344. /*********************************************/
  345. /** PHASE 2: the tesselation process itself. */
  346. /*********************************************/
  347.  
  348. /*** Quads first! */
  349.  
  350.     for (q = quads-1; q >= 0; q--)    /* count down through faces */
  351.     {
  352.         qpoints = 0;
  353.         po0 = qinfo[q].poly;
  354.         p0 = poly[po0].p[0];
  355.         p1 = poly[po0].p[1];
  356.         p2 = poly[po0].p[2];
  357.         p3 = poly[po0].p[3];
  358.         qcurrent = qinfo[q];
  359.  
  360.         /* form the vectors A->B and D->C */
  361.         vec[0].x = point[p1].x - point[p0].x;
  362.         vec[0].y = point[p1].y - point[p0].y;
  363.         vec[0].z = point[p1].z - point[p0].z;
  364.         vec[1].x = point[p2].x - point[p3].x;
  365.         vec[1].y = point[p2].y - point[p3].y;
  366.         vec[1].z = point[p2].z - point[p3].z;
  367.  
  368.         for (row = 0; row <= freq; row++)    /* there are frequency+1 rows */
  369.         {
  370.             /* prev is the index at the start of the previous row */
  371.             prev = (row * (row-1)) / 2;
  372.  
  373.             start.x = point[p0].x + (row * vec[0].x / freq);
  374.             start.y = point[p0].y + (row * vec[0].y / freq);
  375.             start.z = point[p0].z + (row * vec[0].z / freq);
  376.  
  377.             end.x = point[p3].x + (row * vec[1].x / freq);
  378.             end.y = point[p3].y + (row * vec[1].y / freq);
  379.             end.z = point[p3].z + (row * vec[1].z / freq);
  380.  
  381.             vec[2].x = end.x - start.x;
  382.             vec[2].y = end.y - start.y;
  383.             vec[2].z = end.z - start.z;
  384.  
  385. /** handle left edge */
  386.             /* the corners are special cases */
  387.             if (row == 0)
  388.                 qpoint[qpoints++] = p0;    /* top */
  389.             else if (row == freq)
  390.                 qpoint[qpoints++] = p1;    /* bottom left */
  391.             else
  392.             {
  393.                 /* This is the first side (point 0 to point 1) */
  394.                 if (qcurrent.present & 1)
  395.                 {
  396.                     if (qcurrent.kind[0] == K_QUAD)
  397.                     {
  398.                         /* these edge points belong to another quad */
  399.                         adj_quad = qcurrent.index[0];
  400.                         adj_edge = (qcurrent.edge & 3);
  401.                         pos = (qcurrent.direction & 1 ? freq-row-1 : row-1);
  402.                         qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  403.                     }
  404.                     else sys_exit("fatal error 1");    /* should never occur! */
  405.                 }
  406.                 else
  407.                 {
  408.                     /* these edge points belong to THIS face; create point */
  409.                     qpoint[qpoints++] = points;
  410.                     qinfo[q].edge_point[0][row-1] = points;
  411.                     add_point(start.x, start.y, start.z);
  412.                 }
  413.             }
  414.  
  415. /** move across, left to right */
  416.             for (i = 1; i <= freq; i++)
  417.             {
  418.                 add_the_point = 0;
  419.  
  420.                 /* This point may be the bottom corner */
  421.                 if (row == freq && i == freq) qpoint[qpoints++] = p2;
  422.  
  423.                 /* Or the upper right corner */
  424.                 else if (row == 0 && i == freq) qpoint[qpoints++] = p3;
  425.  
  426.                 /* or it's the second side (point 1 to point 2) */
  427.                 else if (row == freq && i != freq)
  428.                 {
  429.                     if (qcurrent.present & 2)    /* the edge exists */
  430.                     {
  431.                         adj_quad = qcurrent.index[1];
  432.                         adj_edge = (qcurrent.edge >> 2) & 3;
  433.                         pos = (qcurrent.direction & 2 ? freq-i-1 : i-1);
  434.                         qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  435.                     }
  436.                     else    /* the edge must be created */
  437.                     {
  438.                         qinfo[q].edge_point[1][i-1] = points;
  439.                         add_the_point = 1;
  440.                     }
  441.                 }
  442.  
  443.                 /* or it's the third side (point 2 to point 3) */
  444.                 else if (row != 0 && row != freq && i == freq)
  445.                 {
  446.                     if (qcurrent.present & 4)    /* the edge exists */
  447.                     {
  448.                         adj_quad = qcurrent.index[2];
  449.                         adj_edge = (qcurrent.edge >> 4) & 3;
  450.                         /* the following is backwards: subtle note below */
  451.                         pos = (qcurrent.direction & 4 ? row-1 : freq-row-1);
  452.                         qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  453.                     }
  454.                     else    /* the edge is created and specially numbered */
  455.                     {
  456.                         /* subtle point: we must be careful that the edge
  457.                             vertices are entered in the same clockwisdom
  458.                             as the vector point2->point0 */
  459.                         qinfo[q].edge_point[2][freq-row-1] = points;
  460.                         add_the_point = 1;
  461.                     }
  462.                 }
  463.  
  464.                 /* or it's the fourth side (point 3 to point 0) */
  465.                 else if (row == 0 && i != freq)
  466.                 {
  467.                     if (qcurrent.present & 8)    /* the edge exists */
  468.                     {
  469.                         adj_quad = qcurrent.index[3];
  470.                         adj_edge = (qcurrent.edge >> 6) & 3;
  471.                         /* the following is backwards: subtle note below */
  472.                         pos = (qcurrent.direction & 8 ? i-1 : freq-i-1);
  473.                         qpoint[qpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  474.                     }
  475.                     else    /* the edge is created and specially numbered */
  476.                     {
  477.                         /* subtle point: we must be careful that the edge
  478.                             vertices are entered in the same clockwisdom
  479.                             as the vector point2->point0 */
  480.                         qinfo[q].edge_point[3][freq-i-1] = points;
  481.                         add_the_point = 1;
  482.                     }
  483.                 }
  484.  
  485.                 /* otherwise, it's a point in the middle we need to create */
  486.                 else add_the_point = 1;
  487.  
  488.                 if (add_the_point)
  489.                 {
  490.                     qpoint[qpoints++] = points;
  491.                     add_point(start.x + (i * vec[2].x / freq),
  492.                               start.y + (i * vec[2].y / freq),
  493.                               start.z + (i * vec[2].z / freq));
  494.                 }
  495.                 if (row != 0)
  496.                 {
  497.                     allocate_poly(4, colors.newface);
  498.                     poly[polys].p[0] = qpoint[(row-1)*(freq+1)+i-1];
  499.                     poly[polys].p[1] = qpoint[  row  *(freq+1)+i-1];
  500.                     poly[polys].p[2] = qpoint[  row  *(freq+1)+i  ];
  501.                     poly[polys].p[3] = qpoint[(row-1)*(freq+1)+i  ];
  502.                     finish_poly(0);
  503.                 }
  504.             }
  505.         }
  506.     }
  507.  
  508. /********* now do the faces */
  509.  
  510.     for (f = faces-1; f >= 0; f--)    /* count down through faces */
  511.     {
  512.         fpoints = 0;
  513.         p0 = face[f].p[0];
  514.         p1 = face[f].p[1];
  515.         p2 = face[f].p[2];
  516.         fcurrent = finfo[f];
  517.  
  518.         /* form the vectors A->B and B->C */
  519.         vec[0].x = point[p1].x - point[p0].x;
  520.         vec[0].y = point[p1].y - point[p0].y;
  521.         vec[0].z = point[p1].z - point[p0].z;
  522.         vec[1].x = point[p2].x - point[p1].x;
  523.         vec[1].y = point[p2].y - point[p1].y;
  524.         vec[1].z = point[p2].z - point[p1].z;
  525.  
  526.         for (row = 0; row <= freq; row++)    /* there are frequency+1 rows */
  527.         {
  528.             /* prev is the index at the start of the previous row */
  529.             prev = (row * (row-1)) >> 1;
  530.  
  531.             start.x = point[p0].x + (row * vec[0].x / freq);
  532.             start.y = point[p0].y + (row * vec[0].y / freq);
  533.             start.z = point[p0].z + (row * vec[0].z / freq);
  534.  
  535. /** handle left edge */
  536.             /* the corners are special cases */
  537.             if (row == 0)
  538.                 fpoint[fpoints++] = p0;    /* top */
  539.             else if (row == freq)
  540.                 fpoint[fpoints++] = p1;    /* bottom left */
  541.             else
  542.             {
  543.                 /* This is the first side (point 0 to point 1) */
  544.                 if (fcurrent.present & 1)
  545.                 {
  546.                     if (fcurrent.kind[0] == K_FACE)
  547.                     {
  548.                         /* these edge points belong to another face */
  549.                         adj_face = fcurrent.index[0];
  550.                         adj_edge = (fcurrent.edge & 3);
  551.                         pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
  552.                         fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  553.                     }
  554.                     else if (fcurrent.kind[0] == K_QUAD)
  555.                     {
  556.                         /* these edge points belong to another face */
  557.                         adj_quad = fcurrent.index[0];
  558.                         adj_edge = (fcurrent.edge & 3);
  559.                         pos = (fcurrent.direction & 1 ? freq-row-1 : row-1);
  560.                         fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  561.                     }
  562.                     else sys_exit("fatal error 2");    /* should never occur! */
  563.                 }
  564.                 else
  565.                 {
  566.                     /* these edge points belong to THIS face; create point */
  567.                     fpoint[fpoints++] = points;
  568.                     finfo[f].edge_point[0][row-1] = points;
  569.                     add_point(start.x, start.y, start.z);
  570.                 }
  571.             }
  572.  
  573. /** move across, left to right */
  574.             for (i = 0; i < row; i++)
  575.             {
  576.                 add_the_point = 0;
  577.  
  578.                 /* This point may be the bottom corner */
  579.                 if (row == freq && i == row-1) fpoint[fpoints++] = p2;
  580.  
  581.                 /* or it's the second side (point 1 to point 2) */
  582.                 else if (row == freq && i != row-1)
  583.                 {
  584.                     if (fcurrent.present & 2)    /* the edge exists */
  585.                     {
  586.                         if (fcurrent.kind[1] == K_FACE)
  587.                         {
  588.                             adj_face = fcurrent.index[1];
  589.                             adj_edge = (fcurrent.edge >> 2) & 3;
  590.                             pos = (fcurrent.direction & 2 ? freq-2-i : i);
  591.                             fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  592.                         }
  593.                         else if (fcurrent.kind[1] == K_QUAD)
  594.                         {
  595.                             adj_quad = fcurrent.index[1];
  596.                             adj_edge = (fcurrent.edge >> 2) & 3;
  597.                             pos = (fcurrent.direction & 2 ? freq-2-i : i);
  598.                             fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  599.                         }
  600.                         else sys_exit("fatal error 3");    /* should never occur! */
  601.                     }
  602.                     else    /* the edge must be created */
  603.                     {
  604.                         finfo[f].edge_point[1][i] = points;
  605.                         add_the_point = 1;
  606.                     }
  607.                 }
  608.  
  609.                 /* or it's the third side (point 2 to point 0) */
  610.                 else if (row != freq && i == row-1)
  611.                 {
  612.                     if (fcurrent.present & 4)    /* the edge exists */
  613.                     {
  614.                         if (fcurrent.kind[2] == K_FACE)
  615.                         {
  616.                             adj_face = fcurrent.index[2];
  617.                             adj_edge = (fcurrent.edge >> 4) & 3;
  618.                             /* the following is backwards: subtle note below */
  619.                             pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
  620.                             fpoint[fpoints++] = finfo[adj_face].edge_point[adj_edge][pos];
  621.                         }
  622.                         else if (fcurrent.kind[2] == K_QUAD)
  623.                         {
  624.                             adj_quad = fcurrent.index[2];
  625.                             adj_edge = (fcurrent.edge >> 4) & 3;
  626.                             /* the following is backwards: subtle note below */
  627.                             pos = (fcurrent.direction & 4 ? row-1 : freq-row-1);
  628.                             fpoint[fpoints++] = qinfo[adj_quad].edge_point[adj_edge][pos];
  629.                         }
  630.                         else sys_exit("fatal error 4");    /* should never occur! */
  631.                     }
  632.                     else    /* the edge is created and specially numbered */
  633.                     {
  634.                         /* subtle point: we must be careful that the edge
  635.                             vertices are entered in the same clockwisdom
  636.                             as the vector point2->point0 */
  637.                         finfo[f].edge_point[2][freq-row-1] = points;
  638.                         add_the_point = 1;
  639.                     }
  640.                 }
  641.                 /* otherwise, it's a point in the middle we need to create */
  642.                 else add_the_point = 1;
  643.  
  644.                 if (add_the_point)
  645.                 {
  646.                     fpoint[fpoints++] = points;
  647.                     add_point(start.x + ((i+1) * vec[1].x / freq),
  648.                               start.y + ((i+1) * vec[1].y / freq),
  649.                               start.z + ((i+1) * vec[1].z / freq));
  650.                 }
  651.                 if (i > 0) add_face(fpoint[prev + i - 1],
  652.                                     fpoint[fpoints - 2],
  653.                                     fpoint[prev + i], colors.newface, 0);
  654.                 add_face(fpoint[prev + i],
  655.                          fpoint[fpoints - 2],
  656.                          fpoint[fpoints - 1], colors.newface, 0);
  657.             }
  658.         }
  659.     }
  660.  
  661.     /* remove the old faces */
  662.     for (f = 0; f < old_faces; f++) delete_face(f, 0);
  663.  
  664.     /* remove the old polys */
  665.     for (q = 0; q < old_polys; q++)
  666.         if (poly[q].verts == 4) delete_poly(q, 0);
  667.  
  668.     /* free our temporary memory */
  669.     if (finfo) sys_free(finfo, sizeof(struct FaceInfo)*old_faces);
  670.     if (qinfo) sys_free(qinfo, sizeof(struct QuadInfo)*quads);
  671.  
  672.     convert_points();
  673.     return OKAY;
  674. }
  675.  
  676.  
  677.